import { NextResponse, type NextRequest } from "next/server";
import { initORM } from "./utils";
import * as jose from "jose";

// !!! in Edge runtime, do not support node.js module , such as 'crypto'
// so can not use jsonwebtoken package, change to jose package

const allowedOrigins = [] as string[];

const corsOptions = {
  "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
  "Access-Control-Allow-Headers":
    "Content-Type, Authorization, Content-Length, X-APP-Secret",
  "Access-Control-Allow-Credentials": "true",
};

export async function middleware(request: NextRequest) {
  // console.log("[middleware]: ", request.method, request.url);

  const oUrl = new URL(request.url);
  const shouldSkipToken =
    oUrl.pathname === "/api/app/config" ||
    oUrl.pathname.startsWith("/api/mock");

  const origin = request.headers.get("origin") ?? "";
  const needToCheckOrigin = allowedOrigins.length > 0;
  const isAllowedOrigin =
    !needToCheckOrigin || allowedOrigins.includes(origin!);
  if (!isAllowedOrigin) {
    return new Response("Not allowed", { status: 403 });
  }

  const isPreflight = request.method === "OPTIONS";
  if (isPreflight) {
    return new Response(null, {
      status: 204,
      headers: Object.assign(
        { "Access-Control-Allow-Origin": origin },
        corsOptions
      ),
    });
  }

  const getResponse = (userId = "") => {
    const headers = new Headers(request.headers);
    headers.set("userid", userId);

    const response = NextResponse.next({
      request: {
        ...request,
        headers: headers,
      },
    });

    if (isAllowedOrigin) {
      response.headers.set("Access-Control-Allow-Origin", origin);
    }

    Object.entries(corsOptions).forEach(([key, value]) => {
      response.headers.set(key, value);
    });

    return response;
  };

  if (shouldSkipToken) {
    return getResponse();
  }

  //   @ts-ignore
  const token = request.cookies.get("token")?.value ?? "";

  if (!token) {
    return new NextResponse(
      JSON.stringify({
        success: false,
        message: "Unauthorized",
        data: { token },
      }),
      {
        status: 401,
        headers: Object.assign(
          { "Access-Control-Allow-Origin": origin },
          corsOptions
        ),
      }
    );

    // return NextResponse.json({
    //   success: false,
    //   message: "Unauthorized",
    //   data: { token },
    // });
  }

  let userId = "";
  let isVerifyFail = false;
  try {
    const decoded = await jose.jwtVerify(
      token,
      new TextEncoder().encode(process.env.JWT_SECRET!)
    );
    // console.log("🚀 ~ middleware ~ decoded:", decoded);

    userId = decoded.payload.userId as string;
  } catch (err) {
    console.log("[middleware]: ", err);
    isVerifyFail = true;
  }

  if (!userId || isVerifyFail) {
    // return NextResponse.redirect(new URL("/login", request.url));

    return new NextResponse(
      JSON.stringify({
        success: false,
        message: "Unauthorized , login again please",
        data: { token },
      }),
      {
        status: 401,
        headers: Object.assign(
          { "Access-Control-Allow-Origin": origin },
          corsOptions
        ),
      }
    );
  }

  return getResponse(userId);

  // request.headers.set("x-user", userId);

  // NextResponse.next(request);
}

export const config = {
  matcher: ["/api/((?!login|logout).*)"],
};
